package com.yonyou.pmclouds.constructionlog.service.rmiimpl;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.consts.BillTypeConst;
import com.yonyou.pmclouds.basecom.entity.PageObject;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.SqlUtil;
import com.yonyou.pmclouds.constructionlog.entity.ConstructionLogListViewVO;
import com.yonyou.pmclouds.constructionlog.entity.ConstructionLogRefVO;
import com.yonyou.pmclouds.constructionlog.entity.ConstructionLogVO;
import com.yonyou.pmclouds.constructionlog.mapper.ConstructionLogMapper;
import com.yonyou.pmclouds.constructionlog.rmiitf.ConstructionLogQuery;
import com.yonyou.pmclouds.inspectitem.entity.InspectItemBillStatusConst;
import com.yonyou.pmclouds.inspectitem.entity.InspectItemVO;
import com.yonyou.pmclouds.inspectitem.mapper.InspectItemMapper;
import com.yonyou.pmclouds.inspectitem.rmiitf.InspectItemService;
import com.yonyou.pmclouds.organization.entity.OrganizationVO;
import com.yonyou.pmclouds.organization.rmiitf.OrganizationQuery;
import com.yonyou.pmclouds.picture.rmiitf.PictureRemoteService;
import com.yonyou.pmclouds.pmpub.entity.QueryListParam;
import com.yonyou.pmclouds.pmpub.rmiitf.IPageQuerySerivce;
import com.yonyou.pmclouds.procedure.entity.ProcedureRefVO;
import com.yonyou.pmclouds.procedure.entity.ProcedureVO;
import com.yonyou.pmclouds.procedure.rmiitf.ProcedureQuery;
import com.yonyou.pmclouds.project.entity.ProjectRefVO;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import com.yonyou.pmclouds.workquality.entity.WorkqualityDetailVO;
import com.yonyou.pmclouds.workquality.entity.WorkqualityVO;
import com.yonyou.pmclouds.workquality.service.rmiitf.WorkqualityQueryService;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.*;

@Service(version = ApplicationConsts.APPLICATION_VERSION,interfaceClass=ConstructionLogQuery.class)
public class ConstructionLogQueryImpl implements ConstructionLogQuery, IPageQuerySerivce<ConstructionLogVO> {
    @Autowired
    private ConstructionLogMapper mapper;
    @Autowired
    private PictureRemoteService picService;
    @Autowired
    private InspectItemService itemService;
    @Autowired
    private ProjectSimpleQuery projectQuery;
    @Autowired
    private ProcedureQuery processQuery;
    @Autowired
    private WorkqualityQueryService qualityQuery;
    @Autowired
    private OrganizationQuery organizationQuery;

    @Autowired
    private InspectItemMapper inspectItemMapper;

    @Override
    public ConstructionLogListViewVO[] queryByProject(String pk_project) throws BusinessException {
        if(StringUtils.isEmpty(pk_project)) {
            return null;
        }
        ConstructionLogListViewVO[]vos = mapper.selectLists(pk_project);
        if(ArrayUtils.isEmpty(vos)) {
            return null;
        }
        //处理检查标准参照【列表态显示】
        String[] pks =  new String[vos.length];

        for (int i = 0; i < vos.length; i++) {
            pks[i] = vos[i].getPk_inspectstandard();
        }
        Map<String, WorkqualityVO> map = qualityQuery.queryByIDs(pks);
        for(ConstructionLogListViewVO vo : vos) {
            WorkqualityVO workqualityVO = map.get(vo.getPk_inspectstandard());
            if (workqualityVO != null) {
                String inspectstandard_name = workqualityVO.getCheckname();
                vo.setInspectstandard_name(inspectstandard_name);
            }
        }
        getPictures(vos);  //添加照片
        return vos;
    }

    /**
     * 添加不合格的检查项中的照片，最多9张
     */
    private void getPictures(ConstructionLogListViewVO[] vos) throws BusinessException {
        Set<String> pkBills = new HashSet<>();
        for(ConstructionLogListViewVO vo : vos){
            if(vo != null && vo.getPk_constructionlog() != null) pkBills.add(vo.getPk_constructionlog());
        }
        if(pkBills.size() == 0) return;

        InspectItemVO[] inspectItemVOS = inspectItemMapper.queryByBillPks(SqlUtil.getSqlIn(pkBills.toArray(new String[0])));
        Map<String, String> recordParent = new HashMap<>();
        if(ArrayUtils.isEmpty(inspectItemVOS)) return;

        pkBills.clear();  //清空集合
        for(InspectItemVO vo : inspectItemVOS){  //取不合格的检查项
            if(vo != null && vo.getBillstatus() == InspectItemBillStatusConst.BILLSTATUS_NO_PASS && vo.getPk_inspectitem() != null){
                pkBills.add(vo.getPk_inspectitem());  //存入检查项主键
                recordParent.put(vo.getPk_inspectitem(), vo.getPk_bill());
            }
        }
        if(pkBills.size() == 0) return;

        Map<String, List<String> > picMap = picService.queryPicsByPkEntitys(pkBills.toArray(new String[0]));
        if(picMap == null) return;
        Map<String, List<String> > parentPicMap = new HashMap<>();

        //得到所有检查项的主键
        for (String key : picMap.keySet()) {
            String pkParent = recordParent.get(key); //检查项主键对应的单据(施工记录)主键
            if (pkParent != null) {   //key是检查项主键
                if (parentPicMap.get(pkParent) == null) {
                    parentPicMap.put(pkParent, new ArrayList<String>());
                }
                if (parentPicMap.get(pkParent).size() < 9) {  //最多取9张照片
                    int need = 9 - parentPicMap.get(pkParent).size();
                    for (int i = 0; i < Math.min(need, picMap.get(key).size()); i++) {
                        parentPicMap.get(pkParent).add(picMap.get(key).get(i));
                    }
                }
            }
        }
        for(ConstructionLogListViewVO vo : vos){
            if(vo != null) vo.setPictures(parentPicMap.get(vo.getPk_constructionlog()));
        }
    }

    /**
     * 添加不合格的检查项中的照片，最多9张
     */
    private void getPictures(ConstructionLogVO[] vos) throws BusinessException {
        Set<String> pkBills = new HashSet<>();
        for(ConstructionLogVO vo : vos){
            if(vo != null && vo.getPk_constructionlog() != null) pkBills.add(vo.getPk_constructionlog());
        }
        if(pkBills.size() == 0) return;

        InspectItemVO[] inspectItemVOS = inspectItemMapper.queryByBillPks(SqlUtil.getSqlIn(pkBills.toArray(new String[0])));
        Map<String, String> recordParent = new HashMap<>();
        if(ArrayUtils.isEmpty(inspectItemVOS)) return;

        pkBills.clear();  //清空集合
        for(InspectItemVO vo : inspectItemVOS){  //取不合格的检查项
            if(vo != null && vo.getBillstatus() == InspectItemBillStatusConst.BILLSTATUS_NO_PASS && vo.getPk_inspectitem() != null){
                pkBills.add(vo.getPk_inspectitem());  //存入检查项主键
                recordParent.put(vo.getPk_inspectitem(), vo.getPk_bill());
            }
        }
        if(pkBills.size() == 0) return;

        Map<String, List<String> > picMap = picService.queryPicsByPkEntitys(pkBills.toArray(new String[0]));
        if(picMap == null) return;
        Map<String, List<String> > parentPicMap = new HashMap<>();

        for (String key : picMap.keySet()) {
            String pkParent = recordParent.get(key); //检查项主键对应的单据(施工记录)主键
            if (pkParent != null) {   //key是检查项主键
                if (parentPicMap.get(pkParent) == null) {
                    parentPicMap.put(pkParent, new ArrayList<String>());
                }
                if (parentPicMap.get(pkParent).size() < 9) {  //最多取9张照片
                    int need = 9 - parentPicMap.get(pkParent).size();
                    for (int i = 0; i < Math.min(need, picMap.get(key).size()); i++) {
                        parentPicMap.get(pkParent).add(picMap.get(key).get(i));
                    }
                }
            }
        }
        for(ConstructionLogVO vo : vos){
            if(vo != null && parentPicMap.get(vo.getPk_constructionlog()) != null)
                vo.setPictures(parentPicMap.get(vo.getPk_constructionlog()).toArray(new String[0]));
        }
    }


    @Override
    public ConstructionLogVO queryOne(String pk_constructionlog) throws BusinessException {
        ConstructionLogVO vo = mapper.getById(pk_constructionlog);
       String pk_bill = vo.getPk_constructionlog();
       // 查询检查项
       InspectItemVO[] itemVOs = itemService.queryByPkbill(pk_bill);
       // 查询照片
       vo.setPictures(queryPics(pk_bill));
       vo.setInspectitems(itemVOs);
       return setRefFiledINfo(vo);
    }

    @Override
    public InspectItemVO queryItemDetail(String pk_inspectItem) throws BusinessException {
        InspectItemVO itemVO = itemService.queryOne(pk_inspectItem);
        return itemVO;
    }



    //没用
    @Override
    public boolean queryRefByIds(String code, String[] ids) throws BusinessException {
        boolean flag = false;
        Integer count = mapper.selectRefByCode(code, ids);
        if(count != null && count > 0) {
            flag = true;
        }
        return flag;
    }

//    没用
    @Override
    public ConstructionLogRefVO[] queryRefsByProject(String pk_project) throws BusinessException {
        if(StringUtils.isEmpty(pk_project)) {
            throw new BusinessException("请传入需要查询的pk_project!");
        }
        ConstructionLogRefVO[] refVOs = mapper.selectRefVOByProject(pk_project);
        if(ArrayUtils.isEmpty(refVOs)) {
            return null;
        }
        return refVOs;
    }
    //    没用
    @Override
    public ConstructionLogRefVO[] queryByIds(String[] ids) throws BusinessException {
        if(ids == null || ids.length==0) {
            throw new BusinessException("请传入需要查询的主键集合!");
        }
        ConstructionLogRefVO[] refVOs = mapper.selectRefByIds(ids);
        if(ArrayUtils.isEmpty(refVOs)) {
            return null;
        }
        return refVOs;
    }

    // 没用 批量填充施工日志关联数据
    @Override
    public List<ConstructionLogVO> queryVosByParams(Map<String, Object> params) throws BusinessException {
        List<ConstructionLogVO> constructionLogVOS = mapper.queryVosByParams(params);
        if (constructionLogVOS.size() > 0) {
            // 批量填充数据
            batchFillFiledInfo(constructionLogVOS);
        }
        return constructionLogVOS;
    }

    @Override
    public PageObject<Object> queryByCondition(String[] pkProject, String[] creators, String startDate, String endDate, int[] billStatus , int start , int size) throws BusinessException {

        int count = mapper.countByCondition(pkProject,creators,startDate,endDate,billStatus);

        ConstructionLogVO[] constructionLogVOs = mapper.queryByCondition(pkProject,creators,startDate,endDate,billStatus,start,size);

        return new PageObject<Object>(setRefFiledInfo(constructionLogVOs),count,start) ;
    }

    /**
     * 批量填充施工日志关联数据
     *
     * @param vos
     * @return void
     * @author yzx
     * @date 2018/6/4 20:15
     */
    private void batchFillFiledInfo(List<ConstructionLogVO> vos) throws BusinessException {
        if (vos == null) {
            return;
        }
        // 收集需要填充数据的相关主键
        Set<String> procedurePks = new HashSet<>();
        Set<String> projectPks = new HashSet<>();
        Set<String> inspectStandardPks = new HashSet<>();
        for (ConstructionLogVO constructionLogVO : vos) {
            procedurePks.add(constructionLogVO.getPk_process());
            projectPks.add(constructionLogVO.getPk_project());
            inspectStandardPks.add(constructionLogVO.getPk_inspectstandard());
        }
        // 工序
        Map<String, ProcedureRefVO> procedureRefVOMap = processQuery.queryRefs(procedurePks.toArray(new String[procedurePks.size()]));
        // 项目
        Map<String, ProjectRefVO> projectRefVOMap = projectQuery.queryRefs(projectPks.toArray(new String[projectPks.size()]));
        // 质量标准
        Map<String, WorkqualityVO> workqualityVOMap = qualityQuery.queryByIDs(inspectStandardPks.toArray(new String[inspectStandardPks.size()]));
        // 填充数据
        for (ConstructionLogVO constructionLogVO : vos) {
            // 工序名称
            if (procedureRefVOMap.get(constructionLogVO.getPk_process()) != null) {
                constructionLogVO.setProcess_name(procedureRefVOMap.get(constructionLogVO.getPk_process()).getSname());
            }
            // 项目信息
            if (projectRefVOMap.get(constructionLogVO.getPk_project()) != null) {
                constructionLogVO.setProject_name(projectRefVOMap.get(constructionLogVO.getPk_project()).getScode());
                constructionLogVO.setProject_name(projectRefVOMap.get(constructionLogVO.getPk_project()).getSname());
            }
            // 检查标准
            if (workqualityVOMap.get(constructionLogVO.getPk_inspectstandard()) != null) {
                constructionLogVO.setInspectstandard_name(workqualityVOMap.get(constructionLogVO.getPk_inspectstandard()).getCheckname());
                // 处理检查项名称及描述
                InspectItemVO[] inspectitems = constructionLogVO.getInspectitems();
                InspectItemVO[] itemVOs = setItemFileds(workqualityVOMap.get(constructionLogVO.getPk_inspectstandard()).getItemtabledata(), inspectitems);
                constructionLogVO.setInspectitems(itemVOs);
            }
        }
    }

    private String[] queryPics(String pk_bill) throws BusinessException {
        return picService.queryPicNamesByPkEntity(pk_bill);
    }

    /**
     * 处理参照字段，非必输项需校验空
     * @param vo
     * @return
     * @throws BusinessException
     */
    private ConstructionLogVO setRefFiledINfo(ConstructionLogVO vo) throws BusinessException {
        if(vo == null) {
            return null;
        }
        String pk_constructionunit = vo.getPk_constructionunit();
        if(!StringUtils.isEmpty(pk_constructionunit)) {

        }
        // 工序
        String pk_process = vo.getPk_process();
        if(!StringUtils.isEmpty(pk_process)) {
            ProcedureVO process = processQuery.getById(pk_process);
            if (process != null) {
                vo.setProcess_name(process.getSname());
            }
        }
        // 项目
        ProjectVO projectVO = projectQuery.queryProject(vo.getPk_project());
        vo.setProject_code(projectVO.getScode());
        vo.setProject_name(projectVO.getSname());
        vo.setManager(projectVO.getManager());

        String pkOrg = projectVO.getPkOrg();
        if(org.apache.commons.lang3.StringUtils.isNotEmpty(pkOrg)) {
            OrganizationVO organizationVO = organizationQuery.queryByPkSrc(RuntimeEnvironment.getTenantId(), pkOrg);
            vo.setOrgName(organizationVO==null?null:organizationVO.getSname());
        }

        // 质量标准名称
        WorkqualityVO workqualityVO = qualityQuery.queryByID(vo.getPk_inspectstandard());
        if (workqualityVO != null) {
            vo.setInspectstandard_name(workqualityVO.getCheckname());
            // 处理检查项名称及描述
            InspectItemVO[] inspectitems = vo.getInspectitems();
            InspectItemVO[] itemVOs = setItemFileds(workqualityVO.getItemtabledata(), inspectitems);
            vo.setInspectitems(itemVOs);
        }
        return vo;
    }

    private InspectItemVO[] setItemFileds(WorkqualityDetailVO[] itemtabledata,
                                                InspectItemVO[] inspectitems) throws BusinessException {
        if(ArrayUtils.isEmpty(inspectitems)) {
            return null;
        }
        Map<String, WorkqualityDetailVO> qualityMap = new HashMap<String,WorkqualityDetailVO>();
        for(WorkqualityDetailVO workqualityDetailVO : itemtabledata) {
            qualityMap.put(workqualityDetailVO.getPkWorkqualitydetail(), workqualityDetailVO);
        }
        for(InspectItemVO itemVO : inspectitems) {
            WorkqualityDetailVO detailVO = qualityMap.get(itemVO.getPk_item());
            if (detailVO != null) {
                itemVO.setItem_content(detailVO.getCheckdescription());
                itemVO.setItem_name(detailVO.getCheckitem());
                itemVO.setExamplePictures(detailVO.getExamplePictures());
            }
        }
        return inspectitems;
    }

    /**
     * 处理参照字段，非必输项需校验空
     *
     * @param vos
     * @return
     * @throws BusinessException
     */
    private ConstructionLogVO[] setRefFiledInfo(ConstructionLogVO[] vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return new ConstructionLogVO[0];
        }

        Set<String> procSet = new HashSet<String>();
        Set<String> projectSet = new HashSet<String>();
        Set<String> standardSet = new HashSet<String>();
        Set<String> pkSet = new HashSet<String>();

        for (ConstructionLogVO vo:
                vos) {
            procSet.add(vo.getPk_process());
            projectSet.add(vo.getPk_project());
            standardSet.add(vo.getPk_inspectstandard());
            pkSet.add(vo.getPk_constructionlog());
        }

        Map<String,ProcedureRefVO>  procedureRefVOMap = processQuery.queryRefs(procSet.toArray(new String[0]));

        Map<String,ProjectVO> projectVOMap = projectQuery.queryProjects(projectSet.toArray(new String[0]));

        Map<String,WorkqualityVO> workqualityVOMap = qualityQuery.queryByIDs(standardSet.toArray(new String[0]));

        InspectItemVO[] itemVOs  =itemService.queryByPkBillsAndStatus(pkSet.toArray(new String[0]),null);

        Map<String,Integer> itemNumsMap = new HashMap<String,Integer>();
        Map<String,Integer> passNumsMap = new HashMap<String,Integer>();

        String tempPkBill = "";
        for (InspectItemVO itemVO :
                itemVOs) {
            tempPkBill = itemVO.getPk_bill();
            if(itemNumsMap.get(tempPkBill) == null){
                itemNumsMap.put(tempPkBill,0);
            }

            if(InspectItemBillStatusConst.BILLSTATUS_NOT_FIT != itemVO.getBillstatus()){
                int num = itemNumsMap.get(tempPkBill) +1;
                itemNumsMap.put(tempPkBill,num);

                if(InspectItemBillStatusConst.BILLSTATUS_PASS == itemVO.getBillstatus()){
                    if(passNumsMap.get(tempPkBill) == null){
                        passNumsMap.put(tempPkBill,0);
                    }
                    int passNum = passNumsMap.get(tempPkBill)+1 ;
                    passNumsMap.put(tempPkBill,passNum);
                }

            }
        }

        for (ConstructionLogVO vo:
                vos) {
            vo.setProcess_name(procedureRefVOMap.get(vo.getPk_process()) == null ? null:procedureRefVOMap.get(vo.getPk_process()).getSname());
            vo.setProject_name(projectVOMap.get(vo.getPk_project()) == null ? null:projectVOMap.get(vo.getPk_project()).getSname());
            vo.setProject_code(projectVOMap.get(vo.getPk_project()) == null ? null:projectVOMap.get(vo.getPk_project()).getScode());
            vo.setInspectstandard_name(workqualityVOMap.get(vo.getPk_inspectstandard()) == null ? null : workqualityVOMap.get(vo.getPk_inspectstandard()).getCheckname());
            vo.setTotItemNum(itemNumsMap.get(vo.getPk_constructionlog()) == null ? 0 : itemNumsMap.get(vo.getPk_constructionlog()));
            vo.setPassNum(passNumsMap.get(vo.getPk_constructionlog()) == null ?0 :passNumsMap.get(vo.getPk_constructionlog()));
            vo.setUnPassNum(vo.getTotItemNum()-vo.getPassNum());

            if(BigDecimal.ZERO.equals(vo.getTotItemNum()) ){
                vo.setPassRate(BigDecimal.ZERO);
            }else{
                if (vo.getTotItemNum() > 0) {
                    vo.setPassRate(new BigDecimal(((double) vo.getPassNum() / (double) vo.getTotItemNum()) * 100).setScale(2, BigDecimal.ROUND_HALF_UP));
                }
            }

        }

        return vos;
    }

    @Override
    public int countByProject(QueryListParam param) throws BusinessException{

        int count = mapper.countByCondition( new String[]{param.getPkProject()}, null, param.getStartDate(), param.getEndDate(), null);

        return count;
    }

    @Override
    public ConstructionLogVO[] queryByProject(QueryListParam param) throws BusinessException {

        ConstructionLogVO[] vos = mapper.queryByCondition(new String[]{param.getPkProject()}, null, param.getStartDate(), param.getEndDate(), null,param.getPageStart(),param.getPageSize());
        String[] pks =  new String[vos.length];

        for (int i = 0; i < vos.length; i++) {
            pks[i] = vos[i].getPk_inspectstandard();
        }
        Map<String, WorkqualityVO> map = qualityQuery.queryByIDs(pks);
        for(ConstructionLogVO vo : vos) {
            WorkqualityVO workqualityVO = map.get(vo.getPk_inspectstandard());
            if (workqualityVO != null) {
                String inspectstandard_name = workqualityVO.getCheckname();
                vo.setInspectstandard_name(inspectstandard_name);
            }
        }
        getPictures(vos);

        return vos;
    }


    @Override
    public String getBillType() {
        return BillTypeConst.CONSTRUCTIONLOG_BILLTYPE;
    }
}
